package com.boot.utils;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;


/**
 * <p>Http工具类
 *
 * <p>Http工具类，为系统提供通用Http访问操作方法：
 *
 * <p>1、发送GET请求；
 * <p>2、发送POST请求。
 *
 */
public class HttpUtils {

    /**
     * <p>发送GET请求
     *
     * @param  url GET请求地址
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     */
    public static String doGet(String url) {

        return HttpUtils.doGet(url , null , null , 0);
    }

    /**
     * <p>发送GET请求
     *
     * @param  url       GET请求地址
     * @param  headerMap GET请求头参数容器
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     */
    public static String doGet(String url , Map headerMap) {

        return HttpUtils.doGet(url , headerMap , null , 0);
    }

    /**
     * <p>发送GET请求
     *
     * @param  url       GET请求地址
     * @param  proxyUrl  代理服务器地址
     * @param  proxyPort 代理服务器端口号
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     * @modify 窦海宁, 2012-03-19
     */
    public static String doGet(String url , String proxyUrl , int proxyPort) {

        return HttpUtils.doGet(url , null , proxyUrl , proxyPort);
    }

    /**
     * <p>发送GET请求
     *
     * @param  url       GET请求地址
     * @param  headerMap GET请求头参数容器
     * @param  proxyUrl  代理服务器地址
     * @param  proxyPort 代理服务器端口号
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     * @modify 窦海宁, 2012-03-19
     */
    public static String doGet(String url , Map headerMap , String proxyUrl , int proxyPort) {

        String     content    = null;
        HttpClient httpClient = new HttpClient();
        GetMethod getMethod  = new GetMethod(url);

        if (headerMap != null) {

            //头部请求信息
            if (headerMap != null) {

                Iterator iterator = headerMap.entrySet().iterator();
                while (iterator.hasNext()) {

                    Entry entry = (Entry) iterator.next();
                    getMethod.addRequestHeader(entry.getKey().toString() , entry.getValue().toString());
                }
            }
        }

        if (StringUtils.isNotBlank(proxyUrl)) {

            httpClient.getHostConfiguration().setProxy(proxyUrl , proxyPort);
        }

        //设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT , 10000);
        //postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER , new DefaultHttpMethodRetryHandler());
        InputStream inputStream = null;
        try {

            if (httpClient.executeMethod(getMethod) == HttpStatus.SC_OK) {

                //读取内容
                //inputStream = getMethod.getResponseBodyAsStream();
                content     = getMethod.getResponseBodyAsString();
            } else {

                System.err.println("Method failed: " + getMethod.getStatusLine());
            }
        } catch (IOException ex) {

            ex.printStackTrace();
        } finally {

            IOUtils.closeQuietly(inputStream);
            getMethod.releaseConnection();
        }
        return content;
    }

    /**
     * <p>发送POST请求
     *
     * @param  url          POST请求地址
     * @param  parameterMap POST请求参数容器
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     */
    public static String doPost(String url , Map parameterMap) {

        return HttpUtils.doPost(url , null , parameterMap , null , null , 0);
    }

    /**
     * <p>发送POST请求
     *
     * @param  url          POST请求地址
     * @param  parameterMap POST请求参数容器
     * @param  paramCharset 参数字符集名称
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     * @modify 窦海宁, 2012-05-21
     */
    public static String doPost(String url , Map parameterMap , String paramCharset) {

        return HttpUtils.doPost(url , null , parameterMap , paramCharset , null , 0);
    }

    /**
     * <p>发送POST请求
     *
     * @param  url          POST请求地址
     * @param  headerMap    POST请求头参数容器
     * @param  parameterMap POST请求参数容器
     * @param  paramCharset 参数字符集名称
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     * @modify 窦海宁, 2012-05-21
     */
    public static String doPost(String url , Map headerMap , Map parameterMap , String paramCharset) {

        return HttpUtils.doPost(url , headerMap , parameterMap , paramCharset , null , 0);
    }

    /**
     * <p>发送POST请求
     *
     * @param  url          POST请求地址
     * @param  parameterMap POST请求参数容器
     * @param  paramCharset 参数字符集名称
     * @param  proxyUrl     代理服务器地址
     * @param  proxyPort    代理服务器端口号
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     */
    public static String doPost(String url , Map parameterMap , String paramCharset , String proxyUrl , int proxyPort) {

        return HttpUtils.doPost(url , null , parameterMap , paramCharset , proxyUrl , proxyPort);
    }

    /**
     * <p>发送POST请求
     *
     * @param  url          POST请求地址
     * @param  headerMap    POST请求头参数容器
     * @param  parameterMap POST请求参数容器
     * @param  paramCharset 参数字符集名称
     * @param  proxyUrl     代理服务器地址
     * @param  proxyPort    代理服务器端口号
     *
     * @return 与当前请求对应的响应内容字节数组
     *
     * @modify 窦海宁, 2012-05-21
     */
    public static String doPost(String url , Map headerMap , Map parameterMap , String paramCharset , String proxyUrl , int proxyPort) {

        String     content    = null;
        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod(url);

        if (StringUtils.isNotBlank(paramCharset)) {

            postMethod.getParams().setContentCharset(paramCharset);
            postMethod.getParams().setHttpElementCharset(paramCharset);
        }

        if (headerMap != null) {

            //头部请求信息
            if (headerMap != null) {

                Iterator iterator = headerMap.entrySet().iterator();
                while (iterator.hasNext()) {

                    Entry entry = (Entry) iterator.next();
                    postMethod.addRequestHeader(entry.getKey().toString() , entry.getValue().toString());
                }
            }
        }

        Iterator iterator = parameterMap.keySet().iterator();
        while (iterator.hasNext()) {

            String key = (String) iterator.next();
            postMethod.addParameter(key , (String) parameterMap.get(key));
        }

        if (StringUtils.isNotBlank(proxyUrl)) {

            httpClient.getHostConfiguration().setProxy(proxyUrl , proxyPort);
        }

        //设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
        postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT , 10000);
        //postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER , new DefaultHttpMethodRetryHandler());
        InputStream inputStream = null;
        try {

            if (httpClient.executeMethod(postMethod) == HttpStatus.SC_OK) {

                //读取内容
                //inputStream = postMethod.getResponseBodyAsStream();
                content     = postMethod.getResponseBodyAsString();
            } else {

                System.err.println("Method failed: " + postMethod.getStatusLine());
            }
        } catch (IOException ex) {

            ex.printStackTrace();
        } finally {

            IOUtils.closeQuietly(inputStream);
            postMethod.releaseConnection();
        }
        return content;
    }
    /**
     * httpclient4.3 ClientWithResponseHandler
     */
    public static String httpGet(String url, int timeout, final String charset, Map<String, String> headParamMap) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpGet httpget = new HttpGet(url);
            // # 设置http header
            if (headParamMap != null && headParamMap.size() > 0) {
                Iterator<String> it = headParamMap.keySet().iterator();
                while (it.hasNext()) {
                    String name = it.next();
                    String value = headParamMap.get(name);
                    httpget.setHeader(name, value);
                }
            }

            if (timeout > 0) {
                // 请求超时 读取超时
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httpget.setConfig(requestConfig);
            }
            // Create a custom response handler
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        if (entity != null) {
                            byte[] bytearray = EntityUtils.toByteArray(entity);
                            return new String(bytearray, charset);
                        }
                        return null;
                    } else {
                        // throw new ClientProtocolException("Unexpected response status: " + status);
                        return null;
                    }
                }
            };
            String responseBody = httpclient.execute(httpget, responseHandler);

            return responseBody;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * httpclient4.3 post请求
     *
     * @throws InvokeException
     */
    public static String httpPost(String url, List<NameValuePair> params, int timeout, String charset, Map<String, String> headParamMap) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

            // # 设置http header
            if (headParamMap != null && headParamMap.size() > 0) {
                Iterator<String> it = headParamMap.keySet().iterator();
                while (it.hasNext()) {
                    String name = it.next();
                    String value = headParamMap.get(name);
                    httppost.setHeader(name, value);
                }
            }
            if (timeout > 0) {
                // 请求超时 读取超时
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httppost.setConfig(requestConfig);
            }
            CloseableHttpResponse response = httpclient.execute(httppost);
            InputStreamReader inputStreamReader = null;
            BufferedReader rd = null;
            try {
                inputStreamReader = new InputStreamReader(response.getEntity().getContent(), charset);
                rd = new BufferedReader(inputStreamReader);
                StringBuilder responseStr = new StringBuilder();
                String line;
                while ((line = rd.readLine()) != null) {
                    responseStr.append(line);
                }
                return responseStr.toString();
            } finally {
                if (rd != null) {
                    rd.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                response.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * httpclient4.3 post请求
     *
     * @throws InvokeException
     */
    public static String httpPostString(String url, String param, String contentType, int timeout, String charset, Map<String, String> headParamMap) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httppost = new HttpPost(url);
            StringEntity reqEntity = new StringEntity(param, charset);
            reqEntity.setContentType(contentType);
            httppost.setEntity(reqEntity);

            // # 设置http header
            if (headParamMap != null && headParamMap.size() > 0) {
                Iterator<String> it = headParamMap.keySet().iterator();
                while (it.hasNext()) {
                    String name = it.next();
                    String value = headParamMap.get(name);
                    httppost.setHeader(name, value);
                }
            }
            if (timeout > 0) {
                // 请求超时 读取超时
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httppost.setConfig(requestConfig);
            }
            CloseableHttpResponse response = httpclient.execute(httppost);
            InputStreamReader inputStreamReader = null;
            BufferedReader rd = null;
            try {
                inputStreamReader = new InputStreamReader(response.getEntity().getContent(), charset);
                rd = new BufferedReader(inputStreamReader);
                StringBuilder responseStr = new StringBuilder();
                String line;
                while ((line = rd.readLine()) != null) {
                    responseStr.append(line);
                }
                return responseStr.toString();
            } finally {
                if (rd != null) {
                    rd.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                response.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static String httpClientUploadFile(String filePath, List<NameValuePair> params, String url, int timeout, String charset,
                                              Map<String, String> headParamMap) {
        return httpClientUploadFile(filePath, params, url, timeout, charset, headParamMap, ContentType.TEXT_PLAIN);
    }

    public static String httpClientUploadFile(String filePath, List<NameValuePair> params, String url, int timeout, String charset,
                                              Map<String, String> headParamMap, ContentType type) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpPost httpPost = new HttpPost(url);
            File file = new File(filePath);
            FileBody bin = new FileBody(file);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            for (NameValuePair param : params) {
                StringBody value = new StringBody(param.getValue(), type);
                builder.addPart(param.getName(), value);
            }
            builder.addPart("file", bin);
            builder.setCharset(CharsetUtils.get("UTF-8"));
            HttpEntity reqEntity = builder.build();

            httpPost.setEntity(reqEntity);
            if (headParamMap != null && headParamMap.size() > 0) {
                Iterator<String> it = headParamMap.keySet().iterator();
                while (it.hasNext()) {
                    String name = it.next();
                    String value = headParamMap.get(name);
                    httpPost.setHeader(name, value);
                }
            }
            if (timeout > 0) {
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
                httpPost.setConfig(requestConfig);
            }
            CloseableHttpResponse response = httpClient.execute(httpPost);
            try {
                HttpEntity resEntity = response.getEntity();
                String responseStr = null;
                if (resEntity != null) {
                    responseStr = EntityUtils.toString(resEntity, Charset.forName("UTF-8"));
                }
                EntityUtils.consume(resEntity);
                return responseStr;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    public static void main(String[] args) {
//        Map<String, String> map = new HashMap<String, String>();
//        map.put("wd", "nima");
//        String b = doGet("http://www.baidu.com", map);
//        System.out.println("-------------------"+b);
        System.out.println(URLEncoder.encode("http://10.23.14.139:8080/pushMonitor/reportCount"));

    }

}